﻿/*
 * Created by SharpDevelop.
 * User: Administrator
 * Date: 3/1/2011
 * Time: 8:30 PM
 * 
 * To change this template use Tools | Options | Coding | Edit Standard Headers.
 */
using System;
using TomatoSynchronizer.Entities;
using TomatoSynchronizer.Store;
using HtmlAgilityPack;
using System.Collections;
using System.Collections.Generic;
using System.Collections.Specialized;

namespace TomatoSynchronizer.Synchronizer
{
	/// <summary>
	/// </summary>
	public static class GuestBookSynchronizer
	{
		public static void Synchronize(Site siteSrc,Site siteDest,HtmlWeb client,SyncDirection direction)
		{
			switch(direction)
			{
				case SyncDirection.Download:
					UpLoadItems(siteDest,siteSrc,client,direction);
					break;
				case SyncDirection.Upload:
					UpLoadItems(siteSrc,siteDest,client,direction);
					break;
				case SyncDirection.DownloadAndUpload:
					UpLoadItems(siteDest,siteSrc,client,SyncDirection.Download);
					UpLoadItems(siteSrc,siteDest,client,SyncDirection.Upload);
					break;
				case SyncDirection.UploadAndDownload:
					UpLoadItems(siteSrc,siteDest,client,SyncDirection.Upload);
					UpLoadItems(siteDest,siteSrc,client,SyncDirection.Download);
					break;
				case SyncDirection.Synchronize:
					MappingStore mappingSrc = UpLoadItems(siteSrc,siteDest,client,SyncDirection.Upload);
					
					GuestBookStore GuestBookStoreDest = new GuestBookStore(siteDest,client);
					var guest_books = GuestBookStoreDest.DownloadItems();
					
					foreach(GuestBook guest_book in guest_books)
					{
						bool sync = false;
						
						foreach(Mapping mapping in mappingSrc.Mappings)
						{
							if(mapping.DestValue == guest_book.guest_books_id)
							{
								sync = true;
							}
						}
						
						if(!sync)
						{
							if(!GuestBookStoreDest.DeleteItem(guest_book.guest_books_id))
							{
								throw new Exception("Could not delete the GuestBook " + guest_book.title + " in site " + GuestBookStoreDest.site.Name);
							}
						}
					}
					break;
			}
		}
		
		private static MappingStore UpLoadItems(Site _siteSrc,Site _siteDest,HtmlWeb client,SyncDirection direction)
		{
			GuestBookStore GuestBookStoreSrc = new GuestBookStore(_siteSrc,client);
			GuestBookStore GuestBookStoreDest = new GuestBookStore(_siteDest,client);
			
			GuestBook[] GuestBooksSrc =  GuestBookStoreSrc.LoadItems();
			GuestBook[] GuestBooksDest =  GuestBookStoreDest.LoadItems();
			
			MappingStore mappingStoreSrc = new MappingStore(_siteSrc,_siteDest,"guest_books_id");
			MappingStore mappingStoreDest = new MappingStore(_siteDest,_siteSrc,"guest_books_id");
			
			mappingStoreSrc.Clean<GuestBook>(GuestBookStoreSrc,GuestBookStoreDest);
			mappingStoreDest.Clean<GuestBook>(GuestBookStoreDest,GuestBookStoreSrc);
			
			MappingStore mappingStore = new MappingStore(_siteSrc,_siteDest,"languages_id");
			
			List<GuestBook> alreadySynchronized = new List<GuestBook>();
			
			foreach(GuestBook GuestBookSrc in GuestBooksSrc)
			{
				//we assume the GuestBook is not yet synchronized
				bool synchronized = false;
				
				//we check if a mapping already exists for this GuestBook in the destination store
				foreach(Mapping mapping in mappingStoreSrc.Mappings)
				{
					if(mapping.SrcValue == GuestBookSrc.guest_books_id && synchronized == false)
					{
						if(!string.IsNullOrEmpty(mapping.DestValue))
						{
							//this GuestBook already exists in the destination store
							//we check if everything changed since the last synchronization
							GuestBook GuestBookDest = GuestBookStoreDest.GetItem(mapping.DestValue);
							if(!string.IsNullOrEmpty(GuestBookDest.guest_books_id))
							{
								synchronized = SynchronizeItem(GuestBookSrc,GuestBookDest);
							}
							else
							{
								//the mapping exists, but the GuestBook has been deleted in the destination store
								//we set a flag that this mapping does not exists anymore
								mapping.Exists = false;
							}
						}
					}
				}
				
				if(!synchronized)
				{
					//there is no mapping, we check if this GuestBook already exists in the destination store
					foreach(GuestBook GuestBookDest in GuestBooksDest)
					{
						//we get the 2 currencies from sites to get sure they really exist
						GuestBook src = GuestBookSrc.Store.GetItem(GuestBookSrc.guest_books_id);
						GuestBook dest = GuestBookDest.Store.GetItem(GuestBookDest.guest_books_id);
						
						if(!string.IsNullOrEmpty(src.guest_books_id))
						{
							if(!string.IsNullOrEmpty(dest.guest_books_id))
							{
								Mapping _mapping = new Mapping(GuestBookSrc.guest_books_id,GuestBookDest.guest_books_id,"guest_books_id");
								mappingStoreSrc.Mappings.Add(_mapping);
								
								synchronized = SynchronizeItem(GuestBookSrc,GuestBookDest);
							}
							else
							{
								synchronized = false;
							}
						}						
					}
				}
				
				if(!synchronized)
				{
					//no mapping the GuestBook is new
					//we insert it in the destination store
					string remoteId = string.Empty;
					
					bool langSet = false;
					MappingStore _mappingStore = new MappingStore(GuestBookSrc.Store.site,GuestBookStoreDest.site,"languages_id");
					foreach(Mapping mapping in _mappingStore.Mappings)
					{
						if(mapping.SrcValue == GuestBookSrc.languages_id)
						{
							GuestBookSrc.languages_id = mapping.DestValue;
							langSet = true;
						}
					}
					
					if(!langSet)
					{
						throw new Exception("Could not get a mapping for language " + GuestBookSrc.languages_id + " in site " + _siteDest.Name);
					}
					
					remoteId = GuestBookStoreDest.InsertItem(GuestBookSrc);
					
					synchronized = remoteId != string.Empty;
					
					if(!synchronized)
					{
						throw new Exception("The GuestBook " + GuestBookSrc.guest_books_id + " has not been synchronized");
					}
					
					Mapping _mapping = new Mapping(GuestBookSrc.guest_books_id,remoteId,"guest_books_id");
					mappingStoreSrc.Mappings.Add(_mapping);
					synchronized = true;
				}
				
				if(!synchronized)
				{
					throw new Exception("could not synchronize the GuestBook " + GuestBookSrc.guest_books_id);
				}
				
//				GuestBookStoreSrc.PersistItem(GuestBookSrc);
				alreadySynchronized.Add(GuestBookSrc);
			}
			
			mappingStoreSrc.Save();
			
			mappingStoreDest.Truncate();
			
			//we save the mappings in the destination MappingStore too
			foreach(Mapping mapping in mappingStoreSrc.Mappings)
			{
				if(mapping.Exists)
				{
					Mapping mappingDest = new Mapping(mapping.DestValue,mapping.SrcValue,mapping.Property);
					mappingStoreDest.Mappings.Add(mappingDest);
				}
			}
			
			mappingStoreDest.Save();
			
			//we check if the 2 MappingStore are synchronized
			if(mappingStoreSrc.Mappings.Count != mappingStoreDest.Mappings.Count)
			{
				throw new Exception("The mapping store for the GuestBooks are not synchronized");
			}
			
			return mappingStoreSrc;
		}
		
		private static bool SynchronizeItem(GuestBook GuestBookSrc,GuestBook GuestBookDest)
		{
			bool synchronized = true;
			
			if(!GuestBookSrc.Equals(GuestBookDest))
			{
				synchronized = false;
				
				//we update the destination GuestBook
				GuestBookSrc.guest_books_id = GuestBookDest.guest_books_id;
				
				bool langSet = false;
				MappingStore _mappingStore = new MappingStore(GuestBookSrc.Store.site,GuestBookDest.Store.site,"languages_id");
				foreach(Mapping mapping in _mappingStore.Mappings)
				{
					if(mapping.SrcValue == GuestBookSrc.languages_id)
					{
						GuestBookSrc.languages_id = mapping.DestValue;
						langSet = true;
					}
				}
				
				if(!langSet)
				{
					throw new Exception("Could not get a mapping for language " + GuestBookSrc.languages_id + " in site " + GuestBookDest.Store.site.Name);
				}
				
				synchronized = GuestBookDest.Store.UpdateItem(GuestBookSrc);
			}
			
			return synchronized;
		}
		
		private static string UploadItem(GuestBookStore GuestBookStoreDest,GuestBook GuestBook)
		{
			string remoteId = string.Empty;
			
			remoteId = GuestBookStoreDest.InsertItem(GuestBook);
			
			return remoteId;
		}
	}
}
